import directions, weapons
from movementData import Plot, Move
from point import Point
from coordinatePlane import CoordPoly
from combatClasses import Attacker, Attackable
from movable import Movable
from utils import NotImplementedWarning

class Boat(Movable, Attacker):
    """Base class for all boats.
    
    A boat is essentially a limited-area container that can act to a
    certain degree.
    """
    damage = None
    wind = None
    #Combat
    cannons = ()
    health = {'rigging':0, 'hull':0}
    healthMax = {'rigging':0, 'hull':0}
    
    #Movable
    location = property(lambda self: self.container.getCoord(self), 
                        lambda self, pos: self.container.moveItemTo(self, pos))
    speedInfo = None
    container = None
    direction = directions.North
    speedInfo = None
    container = None
    _plot=None
    plot = property(lambda self: self._plot, 
                    lambda self: AttributeError('Attribute not writable'))
    
    def __init__(self, game, player, container, initLoc=Point(0.0, 0.0),
                 initDir=directions.North):
        super(Boat, self).__init__(container, initLoc=initLoc, initDir=initDir)
        self.game = game
        self.player = player
        self.cannons = []
      
    ##########
    #MOVEMENT  
    def getLength(self, plot):
        """Return, as a percentage less than one, how far plot goes."""
        length = 0.0
        for m in plot:
            length += plot.dist / self.getMaxMove(plot.dir)
        return length
    
    def getMaxMove(self, direction):
        """Return the farthest this boat can go in that direction."""
        return self.speedInfo[self.wind - plot.dir]

    def getAutoMove(self):
        """Return a plot for drifting."""
        raise NotImplementedWarning

    def getPotentialMoves(self):
        """Return the furthest this boat can go in each direction."""
        raise NotImplementedWarning
    
    ##########
    #ATTACKER
    def hasWeapon(self, weapon):
        """
        Returns True if this attacker has that weapon. Allows some
        default code in the base class.
        """
        return weapon in self.weapons
    
    def addWeapon(self, weapon):
        if not isinstance(weapon, weapons.Cannon):
            return False
        self.cannons.append(weapon)
    
    def getObscured(self, target):
        #TODO: Get obscrured info
        #Draw a line from self to target, check for objects in the middle.
        return False
    
    def getDistance(self, target):
        #TODO: Finish getDistance()
        if target in self.container.items.keys():
            self.container.getDistance(self, target)
        else:
            #I honestly have no clue.
            return 1
    
    ##########
    #ATTACKABLE
    def parry(self, weapon, damage):
        """
        Used to figure out whether a character parries some weapons' 
        damage. Weapon calls this after figuring out how much damage it
        would deal, if weapon can be parried (pistols, rifles, and cannons
        can't be parried).
        """
        return False
    
    def takeDamage(self, damage, weapon, dieRoll=None):
        """
        Tells the target how much damage a weapon thinks the target took,
        in addition to the die roll used to determine that.
        """
        for k, v in damage:
            if k in self.health:
                self.health -= v
    
    def repair(self, modifiers):
        """Repair health by modifier, given on a game-wide scale."""
        for k, v in modifiers:
            self.health[k] += modifiers % self.healthMax[k]
            
    